package com.study.d012Components;

import java.util.concurrent.Callable;
import java.util.concurrent.CyclicBarrier;
import java.util.function.Predicate;
import com.entity.Student;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.Separator;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;

/**
 *
 * ComboBox 下拉列表的使用  以及使用setCellFactory()自定义元素格式
 *
 */
public class ComboBoxMain extends Application{
	private ObservableList<Student> obList=null;
	private int index;    //每次选中的下拉索引

	public static void main(String[] args) {
		launch(args);
	}
	@Override
	public void start(Stage stage) throws Exception {
		AnchorPane aPane = new AnchorPane();

		Label baseLabel = new Label("基本使用：");
		ComboBox<String> cbb1 = new ComboBox<String>();
		cbb1.getItems().addAll("张三","李四","王五","麻子");
		//设置默认显示的条数
		cbb1.setVisibleRowCount(2);

		aPane.getChildren().addAll(baseLabel,cbb1);
		AnchorPane.setTopAnchor(baseLabel, 20.0);
		AnchorPane.setLeftAnchor(baseLabel, 10.0);
		AnchorPane.setTopAnchor(cbb1, 20.0);
		AnchorPane.setLeftAnchor(cbb1, 100.0);

		//设置下拉列表可编辑   ChoiceBox没有这个方法
		cbb1.setEditable(true);
		//设置提示  ，只有是失去焦点时显示
		cbb1.setPromptText("--请选择--");
		//设置占位符，当ComboBox中没有子元素时显示
		cbb1.setPlaceholder(new Label("请输入"));
		//设置失去焦点
		cbb1.setFocusTraversable(false);

		//获取选择的元素
		cbb1.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<String>() {
			@Override
			public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
				System.out.println(newValue);
			}
		});

		//监听输入事件  ，当输入后回车，则将输入的添加到ComboBox中
		cbb1.editorProperty().addListener(new ChangeListener<TextField>() {
			@Override
			public void changed(ObservableValue<? extends TextField> observable, TextField oldValue,
					TextField newValue) {
					String v = newValue.getText();
					if(!"".equals(v) && !cbb1.getItems().contains(v) ){
						cbb1.getItems().add(v);
						cbb1.hide();
						cbb1.show();
					}
			}
		});;


		//例子二： 放入Student 编辑后可以新增
		Label addLabel = new Label("输入后新增：");
		ComboBox<Student> cbb2 = new ComboBox<Student>();
		cbb2.setPrefWidth(200);
		cbb2.setEditable(true);
		Student s1 = new Student("张三", 19);
		Student s2 = new Student("李四", 20);
		Student s3 = new Student("王五", 21);
		cbb2.getItems().addAll(s1,s2,s3);

		AnchorPane.setTopAnchor(addLabel, 70.0);
		AnchorPane.setLeftAnchor(addLabel, 10.0);
		AnchorPane.setTopAnchor(cbb2, 70.0);
		AnchorPane.setLeftAnchor(cbb2, 100.0);
		aPane.getChildren().add(addLabel);
		aPane.getChildren().add(cbb2);
		//添加转换事件
		cbb2.setConverter(new StringConverter<Student>() {

			@Override
			public String toString(Student object) {
				if(object !=null){
					//这个地方需要做null判断，如果第一次元素为空的话会报错
					return object.getName() + '-' + object.getAge();
				}
				return null;
			}

			@Override
			public Student fromString(String value) {
				//value即回车后会输入的数据
				if(value !=null &&  !"".equals(value.trim())){
					//将新增的数据添加到ComboBox中
					Student student=new Student(value, 19);
					cbb2.getItems().add(student);
					return student;
				}
				return null;
			}
		});



		//例子三： 通过关键自己进行检索
		Label queryLabel = new Label("根据关键字检索：");
		ComboBox<Student> cbb3 = new ComboBox<Student>();
		cbb3.setPrefWidth(200);
		cbb3.setEditable(true);
		Student s11 = new Student("张三", 19);
		Student s22 = new Student("李四", 20);
		Student s33 = new Student("王五", 21);
		Student s44 = new Student("小A", 11);
		Student s55 = new Student("小B", 21);
		Student s66 = new Student("小A", 24);
		cbb3.getItems().addAll(s11,s22,s33,s44,s55,s66);



		AnchorPane.setTopAnchor(queryLabel, 130.0);
		AnchorPane.setLeftAnchor(queryLabel, 10.0);
		AnchorPane.setTopAnchor(cbb3, 130.0);
		AnchorPane.setLeftAnchor(cbb3, 100.0);
		aPane.getChildren().add(queryLabel);
		aPane.getChildren().add(cbb3);

		//显示转换
		cbb3.setConverter(new StringConverter<Student>() {

			@Override
			public String toString(Student object) {
				if(object !=null){
					return object.getName() + "-" + object.getAge();
				}
				return null;
			}

			@Override
			public Student fromString(String string) {
				// TODO Auto-generated method stub
				return null;
			}
		});

		//先保存一下原有的元素
		obList = cbb3.getItems();

		//获取输入框    这两种方式都可以
		TextField tField2= cbb3.getEditor();
		TextField tField =cbb3.editorProperty().get();

		//监听输入的值的变化  这个跟鼠标键盘的上下回车键有冲突，点击过滤后的选项后会报错，最后的做法是单独做一个输入框，和ComboBox分开
		tField.textProperty().addListener(new ChangeListener<String>() {
			@Override
			public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
				if(!"".equals(newValue.trim())){
					FilteredList<Student> fs=obList.filtered(new Predicate<Student>() {
						@Override
						public boolean test(Student t) {
							if(t.getName().contains(newValue.trim())){
								return true;
							}
							return false;
						}
					});
					if(fs==null || fs.size() ==0){
						System.out.println("没找到");
						cbb3.setItems(null);
						cbb3.setPlaceholder(new Label("没找到"));
						cbb3.show();
					}else{
						cbb3.setItems(fs);
						cbb3.show();
					}
				}else{
					cbb3.setItems(obList);
					cbb3.show();
				}
			}
		});

		/*tField.textProperty().addListener(new ChangeListener<String>() {

			@Override
			public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
				System.out.println("你输入的是"+newValue);

			}
		});*/


		//例子四：自定义下拉元素的格式
		ComboBox<Student> cbb4 = new ComboBox<Student>();
		Student ss1 = new Student("张三", 19);
		Student ss2 = new Student("李四", 20);
		Student ss3 = new Student("王五", 21);
		Student ss4 = new Student("小A", 11);
		cbb4.getItems().addAll(ss1,ss2,ss3,ss4);

		cbb4.setConverter(new StringConverter<Student>() {
			@Override
			public String toString(Student object) {
				if(object !=null){
					return object.getName() + "-" + object.getAge();
				}
				return null;
			}

			@Override
			public Student fromString(String string) {
				// TODO Auto-generated method stub
				return null;
			}
		});

		Label selfLabel = new Label("自定义下拉元素格式：");
		AnchorPane.setTopAnchor(selfLabel, 170.0);
		AnchorPane.setLeftAnchor(selfLabel, 10.0);
		AnchorPane.setTopAnchor(cbb4, 170.0);
		AnchorPane.setLeftAnchor(cbb4, 140.0);
		aPane.getChildren().add(selfLabel);
		aPane.getChildren().add(cbb4);

		cbb4.setCellFactory(new Callback<ListView<Student>, ListCell<Student>>() {
			@Override
			public ListCell<Student> call(ListView<Student> param) {
				ListCell<Student> listCell = new ListCell<Student>(){

					@Override
					protected void updateItem(Student item, boolean empty) {
						//保留super()方法， 不能删，删除后则无法选中
						super.updateItem(item, empty);

						//使用方式一： 使用默认的setConverter()方法中的toString()方法
						//this.setText(cbb4.getConverter().toString(item));

						//使用方式二：自定义
						if(empty==false){
							HBox hBox = new HBox();
							hBox.setAlignment(Pos.CENTER_LEFT);
							hBox.setStyle("-fx-background-color:#9ACD32");
							Label l1 = new Label(item.getName());
							Label l2 = new Label(String.valueOf(item.getAge()));
							ImageView image = new ImageView("icon/01.jpg");
							image.setFitHeight(15);
							image.setFitWidth(15);
							hBox.getChildren().addAll(image,new Separator(),l1,l2);
							this.setGraphic(hBox);
						}
					}
				};
				return listCell;
			}
		});


		/**
		 * 如果同时实现了setCellFactory() 和cellFactoryProperty().set() 方法，则程序会直接执行后者这个方法，通过查看查看源码可知
		 * setCellFactory()方法还是直接调用的cellFactoryProperty().set(value)方法
		 * 所以，这两个方法用其中一个即可
		 */
		/*cbb4.cellFactoryProperty().set(new Callback<ListView<Student>, ListCell<Student>>() {
			@Override
			public ListCell<Student> call(ListView<Student> param) {
				ListCell<Student>  cell= new ListCell<Student>(){

					@Override
					protected void updateItem(Student item, boolean empty) {
						// TODO Auto-generated method stub
						super.updateItem(item, empty);
						if(empty ==false){
							System.out.println("你走的是这个方法.");
							this.setText(item.getName() + " - cellFactoryProperty -" + item.getAge());
						}
					}
				};

				return cell;
			}
		});
*/


		//例子五：  修改选中的选项
		ComboBox<Student> cbb5 = new ComboBox<Student>();
		Student sss1 = new Student("张三", 19);
		Student sss2 = new Student("李四", 20);
		Student sss3 = new Student("王五", 21);
		Student sss4 = new Student("小A", 11);
		cbb5.getItems().addAll(ss1,sss2,sss3,sss4);

		cbb5.setConverter(new StringConverter<Student>() {

			@Override
			public String toString(Student object) {
				if(object !=null){
					return object.getName() + "-" + object.getAge();
				}
				return null;
			}

			@Override
			public Student fromString(String string) {
				// TODO Auto-generated method stub
				return null;
			}
		});

		Label upLabel  =new Label("修改选项:");
		Button upButton = new Button("修改");
		AnchorPane.setTopAnchor(upLabel, 210.0);
		AnchorPane.setLeftAnchor(upLabel, 10.0);
		AnchorPane.setTopAnchor(cbb5, 210.0);
		AnchorPane.setLeftAnchor(cbb5, 100.0);
		AnchorPane.setTopAnchor(upButton, 210.0);
		AnchorPane.setLeftAnchor(upButton, 250.0);
		aPane.getChildren().addAll(upLabel,cbb5,upButton);

		//获取每次选中的下拉元素索引
		cbb5.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {
			@Override
			public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
				index = newValue.intValue();
				System.out.println("你选择的索引是:" + index);
			}
		});

		//修改元素
		/**
		 * ComboBox在修改时，可以直接修改，然后在清除选项，再设置选项即可
		 * ChoiceBox在修改时， 需要先移除，再将新的元素添加到对应的位置
		 */
		upButton.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
				int temp = index;   //这个索引要保存一下，否则当点击“修改”按钮后索引默认变成了-1
				System.out.println("index="+index);

				cbb5.getItems().get(index).setName("你被修改了");
				cbb5.getItems().get(index).setAge(40);
				cbb5.getSelectionModel().clearSelection();
				cbb5.getSelectionModel().select(temp);
			}
		});


		stage.setScene(new Scene(aPane, 400,300));
		stage.show();

	}
}
